package com.nononsenseapps.feeder.processor

import android.content.Context
import com.nononsenseapps.feeder.db.room.AppDatabase
import com.nononsenseapps.feeder.db.entity.Feed
import com.nononsenseapps.feeder.db.entity.FeedItem
import com.nononsenseapps.feeder.processor.interceptor.*
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import timber.log.Timber

class ProcessorManager private constructor(private val interceptors: ArrayList<Interceptor>) {

    /**
     * 发送请求
     */
    suspend fun dispatch(
        feed: Feed,
        feedItem: FeedItem,
        context:Context,
        appDatabase: AppDatabase= AppDatabase.getInstance(context)
    ): FeedItem {
        Timber.d("ProcessorManager dispatch......")
        val chain = RealDispatchChain( feed, feedItem ,0,interceptors, appDatabase, RuleManager.INSTANCE!!, processContext = ProcessContext(context))
        val processedItem=chain.proceed(feed,feedItem)
        if (chain.getProcessContext().modifyFlag)
             appDatabase.feedItemDao().updateFeedItem(processedItem)
        return processedItem
    }

    internal interface IBuild {
        fun build(): ProcessorManager
    }

    class ManagerBuilder : IBuild {
        private val interceptors: ArrayList<Interceptor> = arrayListOf()

        fun addInterceptors(vararg interceptors: Interceptor): ManagerBuilder {
            this.interceptors.addAll(interceptors.asList())
            return this
        }

        /**
         * Returns a modifiable list of interceptors that observe the full span of each call: from
         * before the connection is established (if any) until after the response source is selected
         * (either the origin server, cache, or both).
         */
        fun interceptors(): MutableList<Interceptor> = interceptors

        fun addInterceptor(interceptor: Interceptor) = apply {
            interceptors += interceptor
        }

        @JvmName("-addInterceptor") // Prefix with '-' to prevent ambiguous overloads from Java.
        inline fun addInterceptor(crossinline block: (chain: Interceptor.Chain) -> FeedItem) =
            addInterceptor(Interceptor { chain -> block(chain) })


        override fun build(): ProcessorManager {
            return ProcessorManager(interceptors)
        }
    }

    class RealDispatchChain(
        private val feed: Feed,
        private val feedItem: FeedItem,
        private val index: Int,
        private val interceptors: List<Interceptor>,
        private val appDatabase: AppDatabase,
        private val ruleManager: RuleManager,
        private val processContext:ProcessContext
    ) : Interceptor.Chain {
        override fun proceed(feed: Feed, feedItem: FeedItem): FeedItem {
           if (index == interceptors.size) return feedItem

           if (index >= interceptors.size) {
                throw Exception("路由拦截器数量错误")
            }
            val nextChain = RealDispatchChain( feed,feedItem,index + 1, interceptors,appDatabase,ruleManager,processContext)
            val interceptor = interceptors[index]

            return interceptor.intercept(nextChain)
        }

        override fun getFeed(): Feed =feed

        override fun getFeedItem(): FeedItem = feedItem

        override fun getAppDatabase(): AppDatabase = appDatabase

        override fun getRuleManager(): RuleManager = ruleManager

        override fun getProcessContext(): ProcessContext = processContext

    }

    companion object{
        val default=ManagerBuilder()
            .addInterceptor(FullPageCheckerInterceptor())
            //.addInterceptor(LanguageTranInterceptor())
            .addInterceptor(FormatInterceptor())
            .addInterceptor(RuleInterceptor())
            .addInterceptor(UnfoldInterceptor())
            .addInterceptor(PreLoaderItemsInterceptor())
            .build()
    }
}

class ProcessContext(val context:Context){
    var modifyFlag=false

    private var document:Document?=null

    fun getDocument(doc:String):Document{
        if(document==null)
            document= Jsoup.parse(doc)
        return document!!
    }
}